package cn.com.hhrcw.web;

import cn.com.hhrcw.constant.CodeVConstant;
import cn.com.hhrcw.constant.CommonConstant;
import cn.com.hhrcw.entity.*;
import cn.com.hhrcw.login.LoginVO;
import cn.com.hhrcw.login.MobileCodeLogin;
import cn.com.hhrcw.login.PasswordLogin;
import cn.com.hhrcw.message.MechanismService;
import cn.com.hhrcw.message.entity.DepartResult;
import cn.com.hhrcw.message.entity.UserResult;
import cn.com.hhrcw.params.*;
import cn.com.hhrcw.service.*;
import cn.com.hhrcw.sms.service.ISysSmsTemplateService;
import cn.com.hhrcw.thirdLogin.vo.ThridLoginVO;
import cn.com.hhrcw.util.ThirdLoginUtil;
import cn.com.hhrcw.utils.Constant;
import cn.com.hhrcw.utils.SubjectUtils;
import cn.com.hhrcw.validator.resume.util.ResumeRequiredValidationUtil;
import cn.com.hhrcw.vo.MemberThirdStateVO;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.util.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;

/**
 * 验证码登录(验证码块暂时注掉)
 *
 * @author
 * @since 2020年08月12日16:54:16
 */
@RestController
@RequestMapping("/person/code")
@Slf4j
@Validated
public class CodeLoginController extends JeecgController<SysUser, ISysUserService> {
    @Autowired
    private ISysBaseAPI sysBaseApi;

    @Autowired
    private ICvUserWorkInfoService cvUserWorkInfoService;

    @Autowired
    private ICvWorkIntentionService cvWorkIntentionService;

    @Autowired
    private ICvUserEduInfoService cvUserEduInfoService;

    @Autowired
    private IPiInfoService piInfoService;

    @Autowired
    private IMemberThirdService memberThirdService;

    @Autowired
    private MechanismService mechanismService;

    @Autowired
    private ICvResumeService cvResumeService;

    @Autowired
    private ResumeRequiredValidationUtil resumeRequiredValidationUtil;

    @Value("${spring.profiles.active}")
    private String profiles;

    /**
     * 压测环境
     */
    private static final String TEST_2 = "test2";

    /**
     * 登陆
     *
     * @param params
     * @return
     */
    @PostMapping("/login")
    public Result<?> login(@RequestBody @Valid LoginUserParams params) {
        //非手机号+验证码登录情况
        if (StringUtils.isBlank(params.getLoginType())) {
            //对历史数据的处理 ：手机+验证码 默认为null，这里调整为 LOGIN_TYPE_SMSCODE
            params.setLoginType(Constant.LOGIN_TYPE_SMSCODE);
        }

        LoginVO vo = new LoginVO();
        vo.setRoleType(params.getRoleType());
        Integer loginMode = params.getLoginMode();
        boolean isPwd = loginMode == 2;
        if (loginMode != null && isPwd) {
            //测试环境不验证
            if (!StrUtil.equals(profiles, TEST_2)) {
                String captcha = params.getCaptcha();
                if (captcha == null) {
                    return Result.error("验证码错误");
                }
                String lowerCaseCaptcha = captcha.toLowerCase();
                String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + params.getCheckKey(), "utf-8");
                Object checkCode = redisUtil.get(realKey);
                if (checkCode == null || !checkCode.equals(lowerCaseCaptcha)) {
                    return Result.error("验证码错误");
                }
            }
            PasswordLogin passwordLogin = new PasswordLogin(params.getUsername(), params.getPassword(), vo);
            SubjectUtils.login(passwordLogin);
        } else {
            log.info("==XXXXXXXXXXXX==>登录开始 LoginType={},LoginToken={}", params.getLoginType(), params.getLoginToken());
            MobileCodeLogin mobileCodeLogin = new MobileCodeLogin(params.getMobile(), params.getPassword(), vo);
            mobileCodeLogin.setLoginToken(params.getLoginToken());
            mobileCodeLogin.setLoginType(params.getLoginType());

            SubjectUtils.login(mobileCodeLogin);
        }

        SysUser sysUser = (SysUser) redisTemplate.opsForValue().get(CommonConstant.PREFIX_USER_TOKEN + vo.getToken());
        Assert.notNull(sysUser, "登录失败");
        //判断简历是否填写完整
        CvResume one = this.cvResumeService.lambdaQuery()
            .eq(CvResume::getDelFlag, false)
            .eq(CvResume::getUserId, sysUser.getId())
            .eq(CvResume::getType, 0)
            .eq(CvResume::getLanType, 0)
            .one();
        if (one == null) {
            vo.setIsFull(false);
        } else {
            Result valid = resumeRequiredValidationUtil.isValid(one.getId(), true);
            vo.setIsFull(valid.isSuccess());
        }

        String userId = sysUser.getId();
        sysBaseApi.addLog(userId);
        /**** 微信扫描绑定（验证码登录） 处理 begin ****/
        //绑定
        if (params.getLoginType().equalsIgnoreCase(Constant.LOGIN_TYPE_WX_LOGIN_BIND)) {
            log.info("微信扫描绑定（验证码登录） 处理 begin LoginType={} ,thirdToken={}", params.getLoginType(), params.getLoginToken());
            String thirdToken = params.getLoginToken();
            if (StringUtils.isNotBlank(thirdToken)) {
                ThridLoginVO t = (ThridLoginVO) redisTemplate.opsForValue().get(thirdToken);
                if (null == t) {
                    log.warn("thirdToken 没数据 :{}", thirdToken);
                } else {
                    log.info("ThridLoginVO:{}", t);
                    LambdaUpdateWrapper<MemberThird> wrapper = Wrappers.lambdaUpdate();
                    wrapper.eq(MemberThird::getUserId, userId).eq(MemberThird::getThirdType, t.getThirdType());
                    MemberThird memberThird = memberThirdService.getOne(wrapper);
                    if (null != memberThird) {
                        log.warn("重复绑定,放弃");
                    } else {
                        log.info("第三方登录创建");
                        memberThird = new MemberThird();
                        memberThird.setUserId(userId);
                        memberThird.setThirdName(t.getThirdName());
                        memberThird.setThirdType(t.getThirdType());
                        memberThird.setThirdKey(t.getThirdKey());
                        memberThird.setThirdSecondKey(t.getThirdSecondKey());
                        memberThird.setCreateTime(new Date());
                        memberThird.setUpdateTime(new Date());
                        memberThirdService.save(memberThird);

                    }

                }

            }
            log.info("微信扫描绑定（验证码登录） 处理 end");
        }
        return Result.success(vo);
    }

    /**
     * 退出登陆
     *
     * @return
     */
    @PostMapping("/logout")
    public Result<Object> logout() {
        SubjectUtils.logout();
        return Result.ok("账号已退出");
    }

    /**
     * pc第三方 绑定状态查询
     *
     * @param request
     * @param response
     */

    @RequestMapping(value = "/loginState", method = RequestMethod.POST)
    public Result<MemberThirdStateVO> loginThirdState(@RequestBody LoginThirdStateParam param, HttpServletRequest request,
                                                      HttpServletResponse response) {

        MemberThirdStateVO vo = new MemberThirdStateVO();

        MemberThird third = memberThirdService.lambdaQuery()
            .eq(MemberThird::getThirdKey, param.getThirdCode())
            .eq(MemberThird::getThirdSecondKey, param.getSecondId())
            .eq(MemberThird::getThirdType, param.getThirdType()).one();
        vo.setFlag(null != third);

        return Result.ok(vo);
    }

    /**
     * 三方登陆接口
     *
     * @param loginThird
     * @param request
     * @param response
     * @param mobileType
     */
    @RequestMapping(value = "/user/login.thtml", method = RequestMethod.POST)
    public Result loginThird(@RequestBody @Valid LoginThirdParam loginThird, HttpServletRequest request,
                             HttpServletResponse response, @RequestHeader("mobileType") String mobileType) {

        Map<String, Object> ret = new LinkedHashMap<String, Object>();
        Map<String, Object> data = new LinkedHashMap<String, Object>();
        LoginVO vo = new LoginVO();
        try {
            /*
             * 用户户端首先调用三方平台提供的接口：返回唯一标识及用户信息（昵称，头像等）
             * */
            ThirdLoginUtil thirdLoginUtil = new ThirdLoginUtil();
            //判断登录客户端类型调用不同的登录方法；
            //1：PC端微博  2：PC端微信  3：PC端QQ   4：app端QQ  5：app端微信  6:app微博
            boolean isPc = "2".equals(loginThird.getThirdType());
            if (isPc) {
                //调用PC端微信登录方法获取用户信息
                JSONObject o = thirdLoginUtil.pcWxCallback(loginThird.getThirdCode());
                Map map = (Map) JSONObject.toJSON(o);
                boolean success = map.get("errcode") != null;
                boolean errcode = map.get("errcode").equals(40001);
                if (success && errcode) {
                    log.info("code码过期");
                    return Result.error("code码过期");
                }
                //用户唯一标识
                String unionid = (String) o.get("unionid");
                //用户昵称
                String nickname = (String) o.get("nickname");
                //用户性别
                Integer sex = (Integer) o.get("sex");
                //用户头像
                String headimgurl = (String) o.get("headimgurl");
                String thirdType = loginThird.getThirdType();
                data.put("unionid", unionid);
                data.put("nickname", nickname);
                if (sex == 1) {
                    data.put("sex", "0");
                } else {
                    data.put("sex", "1");
                }
                data.put("headimgurl", headimgurl);
                data.put("thirdType", thirdType);
            }
            //会员第三方认证表中查询third_key是否存在唯一标识
            Object unionid = data.get("unionid");
            if (unionid == null) {
                return Result.error("code错误");
            } else {
                LambdaUpdateWrapper<MemberThird> wrapper = Wrappers.lambdaUpdate();
                wrapper.eq(MemberThird::getThirdKey, data.get("unionid")).eq(MemberThird::getThirdType, data.get("thirdType"));
                MemberThird memberThird = memberThirdService.getOne(wrapper);

                if (memberThird != null) {

                    String userId = memberThird.getUserId();

                    //验证用户是否注销
                    SysUser member1 = userService.getById(userId);
                    if (member1.getDelFlag()) {
                        Assert.isTrue(false, "用户不存在");
                    }

                    ret.put("data", data);
                    data.put("userId", userId);
                    sysBaseApi.addLog(userId);
                    String resumeId = (String) redisTemplate.opsForValue().get("FINSH_RESUME_CODE" + userId);
                    if (StringUtils.isBlank(resumeId)) {
                    }
                    vo.setResumId(resumeId);
                    Boolean info = redisTemplate.hasKey(CodeVConstant.FINSH_PIINFO_CODE + userId);
                    vo.setInfoFlag(!info);
                    boolean intention = redisTemplate.hasKey(CodeVConstant.FINSH_INTENTION_CODE + userId).booleanValue();
                    if (intention) {
                        String o = (String) redisTemplate.opsForValue().get(CodeVConstant.FINSH_INTENTION_CODE + userId);
                        vo.setIntentionId(o);
                        vo.setIntentionFlag(false);
                    } else {
                        List<CvWorkIntention> list = cvWorkIntentionService
                            .lambdaQuery()
                            .eq(CvWorkIntention::getUserId, userId)
                            .eq(CvWorkIntention::getDelFlag, false).list();
                        if (CollUtil.isNotEmpty(list)) {
                            vo.setIntentionId(list.get(0).getId());
                        }

                        vo.setIntentionFlag(true);
                    }
                    Boolean edu = redisTemplate.hasKey(CodeVConstant.FINSH_EDU_CODE + userId);
                    if (edu) {
                        String o = (String) redisTemplate.opsForValue().get(CodeVConstant.FINSH_EDU_CODE + userId);
                        vo.setEduId(o);
                        vo.setEduFlag(false);
                    } else {
                        List<CvUserEduInfo> list = cvUserEduInfoService
                            .lambdaQuery()
                            .eq(CvUserEduInfo::getUserId, userId)
                            .eq(CvUserEduInfo::getDelFlag, false)
                            .list();
                        if (CollUtil.isNotEmpty(list)) {
                            vo.setEduId(list.get(0).getId());
                        }

                        vo.setEduFlag(true);
                    }
                    Boolean work = redisTemplate.hasKey(CodeVConstant.FINSH_WORK_CODE + userId);
                    if (work) {
                        String o = (String) redisTemplate.opsForValue().get(CodeVConstant.FINSH_WORK_CODE + userId);
                        vo.setWorkId(o);
                        vo.setWorkFlag(false);
                    } else {
                        List<CvUserWorkInfo> list = cvUserWorkInfoService
                            .lambdaQuery()
                            .eq(CvUserWorkInfo::getUserId, userId)
                            .eq(CvUserWorkInfo::getDelFlag, false)
                            .list();
                        if (CollUtil.isNotEmpty(list)) {
                            vo.setWorkId(list.get(0).getId());
                        }

                        vo.setWorkFlag(true);
                    }

                } else {
                    ret.put("data", data);
                    return Result.error("用户第三方未绑定");
                }

            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error("");
        }
        return Result.ok(vo);
    }

    /**
     * 第三方 注册/登陆
     *
     * @param request
     * @param response
     */

    @RequestMapping(value = "/v1/reg.thtml", method = RequestMethod.POST)
    public Result<?> loginThird(@RequestBody @Valid LoginThirdParam2 loginThird, HttpServletRequest request,
                                HttpServletResponse response) {

        Map<String, Object> ret = new LinkedHashMap<String, Object>();
        Map<String, Object> data = new LinkedHashMap<String, Object>();

        LoginVO vo = new LoginVO();
        //        try {//故意注释，外层有处理
        vo.setRoleType("0");
        SubjectUtils.login(new MobileCodeLogin(loginThird.getPhone(), loginThird.getSmsCode(), vo));
        SysUser sysUser = (SysUser) redisTemplate.opsForValue().get(CommonConstant.PREFIX_USER_TOKEN + vo.getToken());
        if (null != sysUser) {

            String userId = sysUser.getId();
            sysBaseApi.addLog(userId);
            String resumeId = (String) redisTemplate.opsForValue().get("FINSH_RESUME_CODE" + userId);
            if (StringUtils.isBlank(resumeId)) {
            }
            vo.setResumId(resumeId);
            Boolean info = redisTemplate.hasKey(CodeVConstant.FINSH_PIINFO_CODE + userId);
            vo.setInfoFlag(!info);
            Boolean intention = redisTemplate.hasKey(CodeVConstant.FINSH_INTENTION_CODE + userId);
            if (intention) {
                String o = (String) redisTemplate.opsForValue().get(CodeVConstant.FINSH_INTENTION_CODE + userId);
                vo.setIntentionId(o);
                vo.setIntentionFlag(false);
            } else {
                List<CvWorkIntention> list = cvWorkIntentionService
                    .lambdaQuery()
                    .eq(CvWorkIntention::getUserId, userId)
                    .eq(CvWorkIntention::getDelFlag, false).list();
                if (CollUtil.isNotEmpty(list)) {
                    vo.setIntentionId(list.get(0).getId());
                }

                vo.setIntentionFlag(true);
            }
            Boolean edu = redisTemplate.hasKey(CodeVConstant.FINSH_EDU_CODE + userId);
            if (edu) {
                String o = (String) redisTemplate.opsForValue().get(CodeVConstant.FINSH_EDU_CODE + userId);
                vo.setEduId(o);
                vo.setEduFlag(false);
            } else {
                List<CvUserEduInfo> list = cvUserEduInfoService
                    .lambdaQuery()
                    .eq(CvUserEduInfo::getUserId, userId)
                    .eq(CvUserEduInfo::getDelFlag, false)
                    .list();
                if (CollUtil.isNotEmpty(list)) {
                    vo.setEduId(list.get(0).getId());
                }

                vo.setEduFlag(true);
            }
            Boolean work = redisTemplate.hasKey(CodeVConstant.FINSH_WORK_CODE + userId);
            if (work) {
                String o = (String) redisTemplate.opsForValue().get(CodeVConstant.FINSH_WORK_CODE + userId);
                vo.setWorkId(o);
                vo.setWorkFlag(false);
            } else {
                List<CvUserWorkInfo> list = cvUserWorkInfoService
                    .lambdaQuery()
                    .eq(CvUserWorkInfo::getUserId, userId)
                    .eq(CvUserWorkInfo::getDelFlag, false)
                    .list();
                if (CollUtil.isNotEmpty(list)) {
                    vo.setWorkId(list.get(0).getId());
                }

                vo.setWorkFlag(true);
            }
        }
        sysBaseApi.addLog("");
        LambdaUpdateWrapper<MemberThird> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(MemberThird::getThirdType, loginThird.getThirdType()).eq(MemberThird::getUserId, sysUser.getId())
            .eq(MemberThird::getThirdKey, loginThird.getUnionid());
        MemberThird memberByThirdKey = memberThirdService.getOne(wrapper);
        LambdaUpdateWrapper<MemberThird> wrapper1 = Wrappers.lambdaUpdate();
        wrapper1.eq(MemberThird::getThirdKey, loginThird.getUnionid());
        MemberThird byUserIdAndType = memberThirdService.getOne(wrapper1);
        if (byUserIdAndType != null && !byUserIdAndType.getUserId().equals(sysUser.getId())) {
            return Result.error("该第三方账号已被其他用户绑定");
        }
        if (memberByThirdKey != null) {
            log.info("已绑定第三方账号,更新id");
            memberByThirdKey.setThirdKey(loginThird.getUnionid());
            memberByThirdKey.setThirdSecondKey(loginThird.getSecondId());
            memberThirdService.updateById(memberByThirdKey);
        } else {
            log.info("未绑定第三方账号");
            MemberThird memberThird = this.createMemberThird(sysUser.getId(), "", loginThird.getThirdType(), loginThird.getUnionid(), loginThird.getSecondId());
            memberThirdService.saveOrUpdate(memberThird);
        }

        return Result.ok(vo);
    }

    public MemberThird createMemberThird(String userId, String nickName, String thirdType, String openId, String secondId) {
        MemberThird memberThird = new MemberThird();
        //2.会员第三方认证表插入记录

        memberThird.setUserId(userId);
        memberThird.setThirdName(nickName);
        memberThird.setThirdType(thirdType);
        memberThird.setThirdKey(openId);
        memberThird.setThirdSecondKey(secondId);
        memberThird.setCreateTime(new Date());
        memberThird.setUpdateTime(new Date());
        return memberThird;
    }

    /**
     * pc第三方 绑定
     *
     * @param request
     * @param response
     */

    @RequestMapping(value = "/v1/user/3/PcBindThird", method = RequestMethod.POST)
    public Result<?> loginThirdpc(@RequestBody @Valid PcBindThird loginThird, HttpServletRequest request,
                                  HttpServletResponse response) {

        Map<String, Object> ret = new LinkedHashMap<String, Object>();
        Map<String, Object> data = new LinkedHashMap<String, Object>();
        try {
            SysUser sysUser = (SysUser) SubjectUtils.getSubject();
            String userId = loginThird.getUserId();
            String headimgurl = null;
            String sex = null;
            String nickname = null;
            String thirdType = loginThird.getThirdType();
            String unionid = loginThird.getUnionid();
            //PC端 微信绑定

            //判断该第三方账号是否已被其他用户绑定
            LambdaUpdateWrapper<MemberThird> wrapper = Wrappers.lambdaUpdate();
            wrapper.eq(MemberThird::getThirdKey, unionid);
            MemberThird memberThird = memberThirdService.getOne(wrapper);
            LambdaUpdateWrapper<MemberThird> wrapper1 = Wrappers.lambdaUpdate();
            wrapper1.eq(MemberThird::getUserId, loginThird.getUserId()).eq(MemberThird::getThirdType, loginThird.getThirdType());
            MemberThird byUserIdAndType = memberThirdService.getOne(wrapper1);

            if (byUserIdAndType != null && !unionid.equals(byUserIdAndType.getThirdKey())) {
                log.info("该用户已绑定其他第三方账号");
                return Result.error("该用户已绑定其他第三方账号");
            }

            if (memberThird != null) {
                log.info("该第三方账号是否已被其他用户绑定");
                return Result.error("该第三方账号否已被其他用户绑定");
            }

            MemberThird memberThird1 = this.createMemberThird(userId, nickname, thirdType, unionid, loginThird.getSecondId());
            memberThirdService.save(memberThird1);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error("系统发生错误,请等待技术人员处理");
        }

        return Result.ok("绑定成功");
    }

    /**
     * 解绑第三方
     *
     * @param param
     * @return
     */
    @PostMapping(value = "v1/user/third/unbind")
    @ResponseBody
    public Result<?> unbind(@RequestBody @Valid UnbindParam param) {//, HttpServletRequest request,    HttpServletResponse response

        Map<String, Object> data = new LinkedHashMap<String, Object>();
        /**
         * 用户户端首先调用三方平台提供的接口：返回唯一标识及用户信息（昵称，头像等）
         *
         * */
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();
        QueryWrapper<MemberThird> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("USER_ID", sysUser.getId()).eq("THIRD_TYPE", param.getThirdType());
        boolean remove = memberThirdService.remove(queryWrapper);
        return remove ? Result.ok("") : Result.error("删除失败");
    }

    /**
     * 绑定情况
     *
     * @param thirdType 第三方登录类型（例如wx.webapp:微信网站应用 wx.oa:公众号,dd.oa:钉钉）
     * @return
     */
    @GetMapping(value = "v1/user/third/queryBindState")
    @ResponseBody
    public Result<?> queryBindState(String thirdType) {

        Map<String, Object> data = new LinkedHashMap<String, Object>();
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();

        LambdaUpdateWrapper<MemberThird> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(MemberThird::getUserId, sysUser.getId()).eq(MemberThird::getThirdType, thirdType);
        MemberThird memberThird = memberThirdService.getOne(wrapper);
        if (null == memberThird) {
            return Result.ok(null);
        } else {
            return Result.ok(memberThird);
        }

    }

    /**
     * @param request
     * @param response
     */
    @RequestMapping(value = "/getDepart", method = RequestMethod.POST)
    public Result<?> getDepart(HttpServletRequest request,
                               HttpServletResponse response) {
        List<DepartResult> result = mechanismService.getDepartResult();
        return Result.ok(result);
    }

    @Autowired
    private ISysUserDepartService sysUserDepartService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysSmsTemplateService sysSmsTemplateService;

    /**
     * @param request
     * @param response
     */
    @RequestMapping(value = "/getUserList", method = RequestMethod.POST)
    public Result<?> getUserList(HttpServletRequest request,
                                 HttpServletResponse response) {
        List<DepartResult> result = mechanismService.getDepartResult();
        List<UserResult> allList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(result)) {
            for (DepartResult departResult : result) {
                String id = departResult.getId();
                String orgKey = departResult.getAffil_Uniq_Org_Key();
                boolean equals = "MDM_H_2722".equals(orgKey);
                if (equals) {
                    List<UserResult> resultList = mechanismService.getUserResult(id);
                    if (CollectionUtils.isNotEmpty(resultList)) {
                        allList.addAll(resultList);
                    }
                }
            }
        }
        return Result.ok(allList);
    }

}
